# -*- coding: utf-8 -*-
"""Resource Pool"""

import logging
log = logging.getLogger(__name__)
import transaction
import time

from sqlalchemy import Table, Column, Integer, String, Boolean, MetaData, ForeignKey, Text
from sqlalchemy.orm import mapper
from sqlalchemy.orm import relation, backref

from crv.model import DeclarativeBase, metadata, DBSession
from attr import AttrObj, AttrContainer
from crvmodel import Cluster,VM,RoleDef,Role,RoleDefAttr,RoleAttr,VMAttr,ClusterAttr

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ResourcePool (RP)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
class RP(AttrContainer):
    def __init__(self,name="DummyRP",doc="",profilemaker=None,vmmaker=None,clientmaker=None):

        self.AttrClass=RPAttr
        self.setAttr("name",name)
        self.setAttr("doc",doc)
        
        self.setMaker(profilemaker)
        self.setMaker(vmmaker)
        self.setMaker(clientmaker)

    def newVM(self,name):
        return VM(name,rp=self)
        
    def setMaker(self,maker):
        if maker is None:
            return

        makertype=maker.getAttr("makertype")

        if not (makertype == "profile" or makertype == "vm" or makertype == "client"):
            raise RuntimeError("RP:setMaker: Maker type %s is not supported"%makertype)
        
        #First pop the existing maker, if already exists
        for i in range(len(self.makers)):
            if self.makers[i].getAttr("makertype")==makertype:
                self.makers.pop(i)
                break

        #then append the new one
        self.makers.append(maker)

    def getMaker(self,makertype):
        
        if not (makertype == "profile" or makertype == "vm" or makertype == "client"):
            raise RuntimeError("RP:getMaker: Maker type %s is not supported"%makertype)

        for i in range(len(self.makers)):
            if self.makers[i].getAttr("makertype")==makertype:
                return self.makers[i]

        return None

    def check(self):
        pm=getMaker("profile")
        vm=getMaker("vm")
        cm=getMaker("cm")
        
        if (not pm is None) and (pm.check()) and \
           (not vm is None) and (vm.check()) and \
           (not cm is None) and (cm.check()):
            return True
        return False

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# RPAttr
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

class RPAttr(AttrObj):
    pass

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Maker
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
class Maker(AttrContainer):
    def __new__(cls, *args, **kwds):
#        print "Maker.__new__", args, kwds
        cls.AttrClass=MakerAttr
        return AttrContainer.__new__(cls, *args, **kwds)

    def __init__(self,vname="DummyMaker",makertype="undefined"):
        self.AttrClass=MakerAttr
        self.setAttr("name",vname)
        self.setAttr("makertype",makertype)
        
    def check(self):
        raise NotImplementedError
    
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# MakerAttr
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

class MakerAttr(AttrObj):
    pass

class VMMaker(Maker):
    """
    This is the abstract interface that VMManager calls to start/stop VM.
    
    @author Yushu Yao
    @version 0.1
    """

    def __new__(cls, *args, **kwds):
#        print "VMMaker.__new__", args, kwds
        return Maker.__new__(cls, *args, **kwds)

    def __init__(self,vmtype):
        super(VMMaker, self).__init__()
        
        self.setAttr("makertype","vm")
        self.setAttr("vmtype",vmtype)

    def powerOn(self,vm=None):
        """ Will return a vmuuid, in case of Euca or EC2 it's the eki number"""
        raise NotImplementedError

    def powerOff(self,vmuuid):
        raise NotImplementedError

    def ready(self):
        raise NotImplementedError

    def isStopping(self,identifier):
        raise NotImplementedError

    def isStarting(self,identifier):
        raise NotImplementedError

    def isStopped(self,identifier):
        raise NotImplementedError

    def isStarted(self,identifier):
        raise NotImplementedError

    def getIdentifiers(self):
        raise NotImplementedError

class ProfileMaker(Maker):
    """
    This is the abstract interface that VMManager calls to produce the userdata/profile to give the VMs.
    
    @author Yushu Yao
    @version 0.1
    """
    def __new__(cls, *args, **kwds):
#        print "ProfileMaker.__new__", args, kwds
        return Maker.__new__(cls, *args, **kwds)

    def __init__(self,profiletype):
        super(ProfileMaker, self).__init__()
        self.setAttr("makertype","profile")
        self.setAttr("profiletype",profiletype)

    def provideProfile(self,role):
        raise NotImplementedError

    def provideReverseProfile(self,role):
        raise NotImplementedError


class ClientMaker(Maker):
    """
    This is the abstract interface that VMManager calls to produce the userdata/client to give the VMs.
    
    @author Yushu Yao
    @version 0.1
    """

    def __new__(cls, *args, **kwds):
#        print "ClientMaker.__new__", args, kwds
        return Maker.__new__(cls, *args, **kwds)

    def __init__(self,clienttype):
        super(ClientMaker, self).__init__()
        self.setAttr("makertype","client")
        self.setAttr("clienttype",clienttype)

    def makeClient(self,vm):
        """will return a dict {clientuuid->path to a userdata file}"""
        raise NotImplementedError

    def expireClient(self,clientuuid):
        raise NotImplementedError


